/**
 * Copyright (C) Skywares Information Technology, LTD. 
 * All Rights Reserved.
 *
 * MiaoshaController.java created on 2020年2月4日 下午7:17:13 by Lyon Lu 
 */
package com.mvc.server.miaosha.controller;

import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.mvc.server.component.RedisService;
import com.mvc.server.miaosha.access.AccessLimit;
import com.mvc.server.miaosha.pojo.MiaoshaOrder;
import com.mvc.server.miaosha.pojo.MiaoshaUser;
import com.mvc.server.miaosha.pojo.OrderInfo;
import com.mvc.server.miaosha.rabbitmq.MQSender;
import com.mvc.server.miaosha.rabbitmq.MiaoshaMessage;
import com.mvc.server.miaosha.redis.GoodsKey;
import com.mvc.server.miaosha.service.GoodsService;
import com.mvc.server.miaosha.service.MiaoshaService;
import com.mvc.server.miaosha.service.OrderService;
import com.mvc.server.miaosha.vo.GoodsVo;
import com.mvc.server.result.CommonResult;
import com.mvc.server.result.ResultCode;

/**
 * <pre>
 * Description:
 * 
 * @author Lyon Lu
 * @date 2020年2月4日 下午7:17:13
 *
 * </pre>
 */
@Controller
@RequestMapping("/miaosha")
public class MiaoshaController {
	
	@Resource
	private GoodsService goodsService;
	
	@Resource
	private OrderService orderService;
	
	@Resource
	private MiaoshaService miaoshaService;
	
	@Resource
	private RedisService redisService;
	
	@Resource
	private MQSender mqSender;
	
	// 记录秒杀结束货品
	private Map<Long, Boolean> localOverMap =  new HashMap<Long, Boolean>();
	
	@RequestMapping(value = "do_miaosha1")
	public String toMiaosha(MiaoshaUser user, Model model, @RequestParam("goodsId") long goodsId) {
		if (Objects.isNull(user)) {
			return "login";
		}
		model.addAttribute("user", user);

		// 判断库存
		GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
		if (goods.getStockCount() <= 0) {
			model.addAttribute("errmsg", "秒杀结束");
			return "miaosha_fail";
		}

		// 判断是否已经秒杀成功
		MiaoshaOrder order = orderService.getCacheMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
		if (Objects.nonNull(order)) {
			model.addAttribute("errmsg", "重复秒杀");
			return "miaosha_fail";
		}

		// 减库存，下单
		OrderInfo orderInfo = miaoshaService.miaosha(user, goods);

		model.addAttribute("goods", goods);

		model.addAttribute("orderInfo", orderInfo);

		return "order_detail";
	}
	
	@RequestMapping(value = "do_miaosha2")
	@ResponseBody
	public CommonResult<String> doMiaosha(MiaoshaUser user, Model model, @RequestParam("goodsId") long goodsId) {
		if (Objects.isNull(user)) {
			return CommonResult.error(ResultCode.USER_SEEEION_ERROR);
		}
		model.addAttribute("user", user);
		
		// 判断是否已秒杀成功
		MiaoshaOrder order = orderService.getCacheMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
		if (Objects.nonNull(order)) {
			return CommonResult.error(ResultCode.MIAOSHA_REPEATE);
		}
		
		// 获取本地标记，减少对redis访问
		if (localOverMap.containsKey(goodsId)) {
			return CommonResult.error(ResultCode.MIAOSHA_OVER);
		}
		
		// redis预减库存
		Long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, String.valueOf(goodsId), 1);
		if (stock < 0) {
			localOverMap.put(goodsId, true);
			return CommonResult.error(ResultCode.MIAOSHA_OVER);
		}
		
		// 存在可用库存，发送消息队列
		MiaoshaMessage mm = new MiaoshaMessage();
		mm.setUser(user);
		mm.setGoodsId(goodsId);
		mqSender.sendMiaoshaMessage(mm);
		
		
		/*
		 * // 判断库存 GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId); if
		 * (goods.getStockCount() <= 0) { model.addAttribute("errmsg", "秒杀结束"); return
		 * "miaosha_fail"; }
		 * 
		 * // 判断是否已经秒杀成功 MiaoshaOrder order =
		 * orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId); if
		 * (Objects.nonNull(order)) { model.addAttribute("errmsg", "重复秒杀"); return
		 * "miaosha_fail"; }
		 * 
		 * // 减库存，下单 OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
		 * 
		 * model.addAttribute("goods", goods); model.addAttribute("orderInfo",
		 * orderInfo);
		 */
		
		return CommonResult.success();
	}
	
	@RequestMapping(value="/{path}/do_miaosha", method=RequestMethod.POST)
    @ResponseBody
    public CommonResult<Integer> miaosha(Model model,MiaoshaUser user,
    		@RequestParam("goodsId")long goodsId,
    		@PathVariable("path") String path) {
    	model.addAttribute("user", user);
    	if(user == null) {
    		return CommonResult.error(ResultCode.USER_SEEEION_ERROR);
    	}
    	//验证path
    	boolean check = miaoshaService.checkPath(user, goodsId, path);
    	if(!check){
    		return CommonResult.error(ResultCode.VERIFY_CODE_ERROR);
    	}
    	
    	//内存标记，减少redis访问
    	boolean over = localOverMap.get(goodsId);
    	if(over) {
    		return CommonResult.error(ResultCode.MIAOSHA_OVER);
    	}
    	
    	//判断是否已经秒杀到了
    	MiaoshaOrder order = orderService.getCacheMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
    	if(order != null) {
    		return CommonResult.error(ResultCode.MIAOSHA_REPEATE);
    	}
    	
    	//预减库存
    	long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId, 1);//10
    	if(stock < 0) {
    		 localOverMap.put(goodsId, true);
    		return CommonResult.error(ResultCode.MIAOSHA_OVER);
    	}
    	
    	//入队
    	MiaoshaMessage mm = new MiaoshaMessage();
    	mm.setUser(user);
    	mm.setGoodsId(goodsId);
    	mqSender.sendMiaoshaMessage(mm);
    	return CommonResult.success(0);//排队中
    }
	
	@AccessLimit(seconds=5, maxCount=5, needLogin=true)
    @RequestMapping(value="/path", method=RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,
    		@RequestParam("goodsId")long goodsId,
    		@RequestParam(value="verifyCode", defaultValue="0")int verifyCode
    		) {
    	if(user == null) {
    		return CommonResult.error(ResultCode.USER_SEEEION_ERROR);
    	}
    	boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
    	if(!check) {
    		return CommonResult.error(ResultCode.VERIFY_CODE_ERROR);
    	}
    	String path  =miaoshaService.createMiaoshaPath(user, goodsId);
    	return CommonResult.success(path);
    }
    
    
    @RequestMapping(value="/verifyCode", method=RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> getMiaoshaVerifyCod(HttpServletResponse response,MiaoshaUser user,
    		@RequestParam("goodsId")long goodsId) {
    	if(user == null) {
    		return CommonResult.error(ResultCode.USER_SEEEION_ERROR);
    	}
    	try {
    		BufferedImage image  = miaoshaService.createVerifyCode(user, goodsId);
    		OutputStream out = response.getOutputStream();
    		ImageIO.write(image, "JPEG", out);
    		out.flush();
    		out.close();
    		return null;
    	}catch(Exception e) {
    		e.printStackTrace();
    		return CommonResult.error(ResultCode.MIAOSHA_FAIL);
    	}
    }

}
